package org.springblade.modules.mes.opcua.server;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.modules.mes.base.entity.*;
import org.springblade.modules.mes.base.service.IStationAssemblyService;
import org.springblade.modules.mes.opcua.constant.CountMapUtil;
import org.springblade.modules.mes.opcua.constant.OpcUaCache;
import org.springblade.modules.mes.opcua.constant.OpcUaError;
import org.springblade.modules.mes.opcua.constant.OpcUaKey;
import org.springblade.modules.mes.opcua.itf.OpcUa;
import org.springblade.modules.mes.opcua.vo.OpcUaVO;
import org.springblade.modules.mes.quality.entity.AnalysisAssemblyOffline;
import org.springblade.modules.mes.quality.service.IAnalysisAssemblyOfflineService;
import org.springblade.modules.mes.quality.service.IAnalysisMaterialCompositionMysqlService;
import org.springblade.modules.mes.quality.vo.MaterialCountVO;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 产品生产相关
 */
@Service
@AllArgsConstructor
@Slf4j
public class ArchiveService {


	private final IStationAssemblyService stationAssemblyService;

	private final IAnalysisMaterialCompositionMysqlService analysisMaterialCompositionService;

	private final IAnalysisAssemblyOfflineService analysisAssemblyOfflineService;


	private final ToolService toolService;

	/**
	 * 申请总成流水号
	 */
	@DSTransactional
	@DS("master")
	public void stationArchive(OpcUaVO ctx) throws Exception {
		//查询站位
		ProduceSite site = OpcUaCache.getBySiteCode(ctx.getSiteCode());
		if (site == null) {
			toolService.plcMessage(ctx, OpcUaError.E01000);
			OpcUa.getInstance().writeValue(ctx, null, OpcUaKey.archive, (short) 3);
			return;
		}

		List<StationAssembly> stationAssemblys = stationAssemblyService.list(new QueryWrapper<StationAssembly>().lambda()
			.eq(StationAssembly::getStationCode, site.getStationCode())
			.eq(StationAssembly::getSiteCode, site.getSiteCode())
			.eq(StationAssembly::getStatus, 0)
			.orderByDesc(StationAssembly::getCreateTime));
		if (ObjectUtil.isEmpty(stationAssemblys)) {
			toolService.plcMessage(ctx, OpcUaError.E81000);
			OpcUa.getInstance().writeValue(ctx, null, OpcUaKey.archive, (short) 3);
			return;
		}
		//循环归档
		for (StationAssembly stationAssembly : stationAssemblys) {
			//验证物料是否齐全
			Integer result = validStationMaterial(stationAssembly, site);
			if (0 != result) {
				log.warn("当前工位{},订单号{}, 正常归档失败：物料不齐 msg:{}", site.getSiteCode(), stationAssembly.getAssemblyBarcode(), result);
				toolService.plcMessage(ctx, OpcUaError.E81001);
				OpcUa.getInstance().writeValue(ctx, null, OpcUaKey.archive, (short) 3);
				return;
			}
			stationAssembly.setStatus(1);
			stationAssemblyService.saveOrUpdate(stationAssembly);

			//获取当前产品最后工位
			PrdBomStation prdBomStation = toolService.findLastStation(stationAssembly.getAssemblyNo());
			//查询订单
			LMSDetail order = toolService.findOrder(stationAssembly.getAssemblyBarcode());
			//当前工序是最后一个工序
			if (prdBomStation.getStationCode().equals(site.getStationCode())) {

				//完工订单插入
				AnalysisAssemblyOffline analysisAssemblyOffline = new AnalysisAssemblyOffline();
				analysisAssemblyOffline.setAssemblyNo(order.getMatCode());
				analysisAssemblyOffline.setAssemblyBarcode(order.getBarCode());
				analysisAssemblyOffline.setAssemblyName(order.getMatName());
				analysisAssemblyOffline.setAssemblyNewBarcode(order.getBarCode());
				analysisAssemblyOffline.setOnlineTime(stationAssembly.getCreateTime());
				analysisAssemblyOffline.setCompletionTime(new Date());
				analysisAssemblyOffline.setDataState("1");
				analysisAssemblyOfflineService.save(analysisAssemblyOffline);
				//执行完成
				toolService.updateOrderStatus(stationAssembly.getAssemblyBarcode(), 10, null);
				//
			} else {
				//运行中
				toolService.updateOrderStatus(stationAssembly.getAssemblyBarcode(), 2, null);
			}
			//回写计划
			toolService.updatePlanStatus(order.getPlanCode());

		}
		//归档成功
		OpcUa.getInstance().writeValue(ctx, null, OpcUaKey.archive, (short) 2);
	}


	//校验当前工位物料是否齐备
	private Integer validStationMaterial(StationAssembly prdOrder, ProduceSite site) {
		List<PrdBom> matList = toolService.findBomMatListByStation(prdOrder.getAssemblyNo(), prdOrder.getStationCode());
		if (matList == null || matList.size() == 0) {
			return 0;
		}
		//有问题的数据列表，有问题就加入这里
		List<PrdBom> checkPrdBoms = new ArrayList<>();
		List<MaterialCountVO> countList = analysisMaterialCompositionService.matCountByBarCode(prdOrder.getAssemblyBarcode(), site.getStationCode(), site.getSiteCode());
		Map<String, Long> countMap = CountMapUtil.toMap(countList);
		matList.forEach(prdBom -> {
			MaterialInfo m = OpcUaCache.getByMatCode(prdBom.getMaterialNo());
			//不足
			if (Long.valueOf(prdBom.getQuota()) > CountMapUtil.getValue(countMap, m.getMaterialNo())) {
				checkPrdBoms.add(prdBom);
			}
		});
		return checkPrdBoms.size();
	}
}
